/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gpsmap;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.jdesktop.swingx.mapviewer.GeoPosition;
import org.jdesktop.swingx.mapviewer.Waypoint;
import org.openstreetmap.osm.data.MemoryDataSet;
import org.openstreetmap.osm.data.coordinates.LatLon;
import org.openstreetmap.osm.data.searching.NearestStreetSelector;
import org.openstreetmap.osmosis.core.domain.v0_6.*;
import org.openstreetmap.travelingsalesman.routing.Route;
import org.openstreetmap.travelingsalesman.routing.Route.RoutingStep;
import org.openstreetmap.travelingsalesman.routing.routers.TurnRestrictedMultiTargetDijkstraRouter;
import org.openstreetmap.travelingsalesman.routing.selectors.Motorcar;

/**
 *
 * @author Mahdi Abdinejadi, Navid Ranjbar, Amirhossein Tayarani
 */
public class RouteDrawer implements Runnable {

    public void setendPoint(double endPointLAT, double endPointLON) {
        this.endPointLAT = endPointLAT;
        this.endPointLON = endPointLON;
    }
    public GeoPosition getStartPoint(){
        return (new GeoPosition(startpointLAT, startPointLON));
    }

    public void setStartPoint(double startPointLAT, double startPointLON) {
        this.startpointLAT = startPointLAT;
        this.startPointLON = startPointLON;
        System.out.println(startPointLAT + " " + startPointLON);
    }
    WaypointPainter wpPainter = new WaypointPainter();
    private static double startpointLAT = 57.706675, startPointLON = 11.937268, endPointLAT, endPointLON;
    private double startLAT, startLON, endLAT, endLON;
    public int distance = -1;
    private boolean wait = true;
    private boolean walkOrCar = true;
    public Set<Waypoint> wpSet = new HashSet<Waypoint>();
    public ArrayList<Node> node = new ArrayList<Node>();
    MemoryDataSet map = (new org.openstreetmap.osm.io.FileLoader(new File("Map Data//lind_map.osm"))).parseOsm();//amir
    //MemoryDataSet map = (new org.openstreetmap.osm.io.FileLoader(new File("//D:/project/my attemp/lind_map.osm"))).parseOsm();// mehdi
    //MemoryDataSet map = (new org.openstreetmap.osm.io.FileLoader(new File("//Users/navid/NetBeansProjects/trunk/src/gpsmap/resources/map.osm"))).parseOsm();//navid

    public void setThreadWait(boolean wait) {
        this.wait = wait;
    }

    public void setWalkOrCar(boolean walkOrCar) {
        this.walkOrCar = walkOrCar;
    }
    /**This method calls dijkstra methods that have arguments as an input.
     * @author Mahdi Abdinejadi
     */
    public void dijkstra() {
//            System.out.println(startpointLAT+" "+startPointLON+" "+endPointLAT+" "+endPointLON);
        dijkstra(startpointLAT, startPointLON, endPointLAT, endPointLON);

    }
    /** This method sets start point and end point location
     * attention don't mistake this one with the real dijkstra!!!!
     * @author Mahdi Abdinejadi
     */

    public void dijkstra(double startLAT, double startLON, double endLAT, double endLON) {
        this.endLAT = endLAT;
        this.endLON = endLON;
        this.startLAT = startLAT;
        this.startLON = startLON;
    }
    /**  The Thread runs the dijkstra method from the jxmapkit
     * @author Mahdi Abdinejadi
     */
    public void run() {
        
        while (true) {
            try {
                //MemoryDataSet map = (new org.openstreetmap.osm.io.BoundingBoxDownloader(lat0, lon0, lat1, lon1)).parseOsm();
                NearestStreetSelector nSS = new NearestStreetSelector();
                Motorcar vehicle = new Motorcar();
                WalkingSelector walk = new WalkingSelector();
                LatLon startCoord = new LatLon(startLAT, startLON);
                LatLon targetCoord = new LatLon(endLAT, endLON);
                Node startNode = map.getNearestNode(startCoord, nSS);
                Node targetNode = map.getNearestNode(targetCoord, nSS);
                TurnRestrictedMultiTargetDijkstraRouter dijkstra = new TurnRestrictedMultiTargetDijkstraRouter();
                Route theRoute;
                if (walkOrCar) {
                    theRoute = dijkstra.route(map, targetNode, startNode, walk);
                } else {
                    theRoute = dijkstra.route(map, targetNode, startNode, vehicle);
                }
                try {
                    distance = (int) theRoute.distanceInMeters();
                    GPSMapView.distanceLabel.setText(Integer.toString(distance) + "  Meters");
                    for (RoutingStep rs : theRoute.getRoutingSteps()) {
                        Node wayPoint = rs.getStartNode();
                        wpSet.add(new Waypoint(wayPoint.getLatitude(), wayPoint.getLongitude()));
                        for (WayNode wn : rs.getNodes()) {
                            node.add(map.getNodeByID(wn.getNodeId()));
                        }
                    }
//            }
                    
                    wpPainter.setStartTargetWaypoint(new Waypoint(startLAT, startLON), new Waypoint(endLAT, endLON));
                    wpPainter.setNodes(node);
                    wpPainter.setWaypoints(wpSet);
                    GPSMapView.jXMapKit1.getMainMap().setOverlayPainter(wpPainter);
                    GPSMapView. jXMapKit1.setCenterPosition(getStartPoint());
                    GPSMapView.jXMapKit1.setZoom(1);
                    GPSMapView.jXMapKit1.repaint();
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(null, "There Is Not Such A Path", "NOT FOUND", 1);
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }
            wait = true;
            while (wait) {
                try {
                    GPSMapView.jXMapKit1.getMainMap().setOverlayPainter(wpPainter);
//                    GPSMapView.jXMapKit1.setCenterPosition(getStartPoint());
                    GPSMapView.jXMapKit1.repaint();
                    Thread.sleep(3000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(RouteDrawer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}
